﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.MaintenanceUpdates.CApMaintenanceUpdatesApp
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using Microsoft.Win32;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using Tecnomatix.Engineering;
using Tecnomatix.Engineering.Implementation.ModelObjects;


namespace DnProcessSimulateCommands.MaintenanceUpdates;

internal class CApMaintenanceUpdatesApp
{
  private static string _regKeyPath = "SOFTWARE\\Tecnomatix\\eMPower\\MaintenanceUpdates";
  private static string SIEMENS_SUPPORT_CENTER_CONFIG_FILE = "https://dl2.plm.automation.siemens.com/tecnomatix/updates/MaintenanceUpdates.json";
  public static string SIEMENS_SUPPORT_CENTER_ALTERNATIVE_CONFIG_FILE = "https://dl2.plm.automation.siemens.com/tecnomatix/updates/MaintenanceUpdatesAlt.json";
  private const string SERVER_TYPE_ENTRY = "ServerType";
  private const string CUSTOM_CONFIG_LOCATION_ENTRY = "CustomConfigFile";
  private const string SIEMENS_SUPPORT_CENTER_SERVER_ENTRY = "SiemensSupportCenter";
  private const string MAINTENANCE_UPDATES_SECTION = "MaintenanceUpdates";
  private MaintenanceUpdatesConfig _config;

  public CApMaintenanceUpdatesApp(string configFileContent)
  {
    ServicePointManager.Expect100Continue = true;
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    this._config = JsonConvert.DeserializeObject<MaintenanceUpdatesConfig>(configFileContent);
  }

  public static bool IsConfigFileValid(string configFileContent)
  {
    bool flag = true;
    try
    {
      JsonConvert.DeserializeObject<MaintenanceUpdatesConfig>(configFileContent);
    }
    catch (Exception ex)
    {
      CApMaintenanceUpdatesApp.WriteErrorLogMessage($"Invalid config file [{configFileContent}]");
      CApMaintenanceUpdatesApp.WriteExceptionLogMessage(ex);
      flag = false;
    }
    return flag;
  }

  private static bool IsSiemensSupportCenterConfig()
  {
    string regStringValue = CApMaintenanceUpdatesApp.GetRegStringValue(CApMaintenanceUpdatesApp._regKeyPath, "ServerType");
    return string.IsNullOrEmpty(regStringValue) || regStringValue == "SiemensSupportCenter";
  }

  public static bool IsSetupUrlValid(string setupUrl)
  {
    if (!CApMaintenanceUpdatesApp.IsSiemensSupportCenterConfig())
      return true;
    bool flag = setupUrl.StartsWith("https://") && setupUrl.Contains("support.sw.siemens.com");
    if (!flag)
      CApMaintenanceUpdatesApp.WriteErrorLogMessage("Setup link is not a valid Siement Support Center url - " + setupUrl);
    return flag;
  }

  public static bool IsReleaseNotesUrlValid(string releaseNotesUrl)
  {
    if (!CApMaintenanceUpdatesApp.IsSiemensSupportCenterConfig())
      return true;
    bool flag = releaseNotesUrl.StartsWith("https://") && releaseNotesUrl.Contains("docs.sw.siemens.com");
    if (!flag)
      CApMaintenanceUpdatesApp.WriteErrorLogMessage("Release notes link is not a valid documentation url - " + releaseNotesUrl);
    return flag;
  }

  public static void OpenReleaseNotesUrl(string releaseNotesUrl)
  {
    if (!CApMaintenanceUpdatesApp.IsReleaseNotesUrlValid(releaseNotesUrl))
      return;
    Process.Start(releaseNotesUrl);
  }

  private static string GetConfigFileLocation()
  {
    string regStringValue = CApMaintenanceUpdatesApp.GetRegStringValue(CApMaintenanceUpdatesApp._regKeyPath, "CustomConfigFile");
    return CApMaintenanceUpdatesApp.IsSiemensSupportCenterConfig() ? CApMaintenanceUpdatesApp.SIEMENS_SUPPORT_CENTER_CONFIG_FILE : regStringValue;
  }

  private static void WriteErrorLogMessage(string message)
  {
    TxApplication.LogWriter.WriteErrorLine("MaintenanceUpdates - " + message);
  }

  private static void WriteInfoLogMessage(string message)
  {
    TxApplication.LogWriter.WriteInfoLine("MaintenanceUpdates - " + message);
  }

  private static void WriteExceptionLogMessage(Exception ex)
  {
    TxApplication.LogWriter.WriteExceptionLine(ex);
  }

  public static bool DownloadFile(string filePath, out string fileContent)
  {
    fileContent = (string) null;
    if (!filePath.StartsWith("http"))
      return System.IO.File.Exists(filePath);
    try
    {
      using (WebClient webClient = new WebClient())
      {
        ServicePointManager.Expect100Continue = true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        fileContent = webClient.DownloadString(filePath);
      }
    }
    catch (WebException ex)
    {
      CApMaintenanceUpdatesApp.WriteErrorLogMessage($"Failed to download file [{filePath}]");
      CApMaintenanceUpdatesApp.WriteExceptionLogMessage((Exception) ex);
      return false;
    }
    return true;
  }

  public static bool GetConfigFileContent(out string configFileContent)
  {
    configFileContent = (string) null;
    string configFileLocation = CApMaintenanceUpdatesApp.GetConfigFileLocation();
    if (!string.IsNullOrEmpty(configFileLocation))
      return CApMaintenanceUpdatesApp.DownloadFile(configFileLocation, out configFileContent);
    CApMaintenanceUpdatesApp.WriteErrorLogMessage("Empty config file path");
    return false;
  }

  public static string GetDownloadsPath()
  {
    return CApMaintenanceUpdatesApp.SHGetKnownFolderPath(Guid.Parse("374DE290-123F-4565-9164-39C4925E467B"), 0U);
  }

  [DllImport("shell32", CharSet = CharSet.Unicode, PreserveSig = false)]
  private static extern string SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, int hToken = 0);

  public void RunSetup(string zipFilePath)
  {
    if (!System.IO.File.Exists(zipFilePath))
    {
      CApMaintenanceUpdatesApp.WriteErrorLogMessage("Cannot run the setup because the zip file is missing - " + zipFilePath);
    }
    else
    {
      string str1 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
      if (Directory.Exists(str1))
        Directory.Delete(str1, true);
      ZipFile.ExtractToDirectory(zipFilePath, str1);
      string searchPattern = "*.exe";
      string[] files = Directory.GetFiles(str1, searchPattern);
      if (files.Length != 1)
        return;
      string str2 = files[0];
      new Process() { StartInfo = { FileName = str2 } }.Start();
    }
  }

  public bool? IsNewVersion(out VersionDeclarationEntry newVersionInfo)
  {
    newVersionInfo = (VersionDeclarationEntry) null;
    string currentVersion = this.GetCurrentVersion();
    bool flag = false;
    if (!string.IsNullOrEmpty(currentVersion))
    {
      VersionsBindingSource versions = this._config.Versions;
      string currentMajorVersion = currentVersion.Split('.')[0];
      VersionEntry sameUpdateVersion = versions.FirstOrDefault<VersionEntry>((Func<VersionEntry, bool>) (x => x.MajorVersion == currentMajorVersion));
      if (sameUpdateVersion != null)
      {
        newVersionInfo = this._config.VersionsDefinitions.FirstOrDefault<VersionDeclarationEntry>((Func<VersionDeclarationEntry, bool>) (x => x.UpdateVersion == sameUpdateVersion.UpdateVersion));
        if (newVersionInfo != null)
        {
          flag = this.IsNewVersionInternal(currentVersion, newVersionInfo.UpdateVersion);
          if (flag)
          {
            string setup = newVersionInfo.Setup;
            string releaseNotes = newVersionInfo.ReleaseNotes;
            string hash = newVersionInfo.Hash;
            if (string.IsNullOrEmpty(setup))
            {
              CApMaintenanceUpdatesApp.WriteErrorLogMessage($"No \"setup\" entry for version {newVersionInfo.UpdateVersion}.");
              return new bool?();
            }
            if (string.IsNullOrEmpty(releaseNotes))
            {
              CApMaintenanceUpdatesApp.WriteErrorLogMessage($"No \"release_notes\" entry for version {newVersionInfo.UpdateVersion}.");
              return new bool?();
            }
            if (string.IsNullOrEmpty(hash))
            {
              CApMaintenanceUpdatesApp.WriteErrorLogMessage($"No \"sha256\" entry for version {newVersionInfo.UpdateVersion}.");
              return new bool?();
            }
          }
        }
        else
        {
          CApMaintenanceUpdatesApp.WriteErrorLogMessage($"Cannot find information for version {sameUpdateVersion.UpdateVersion} in the config file.");
          return new bool?();
        }
      }
      return new bool?(flag);
    }
    CApMaintenanceUpdatesApp.WriteErrorLogMessage("Failed to retrieve current version.");
    return new bool?();
  }

  private static string ComputeSha256Hash(string filename)
  {
    using (SHA256 shA256 = SHA256.Create())
    {
      using (FileStream inputStream = System.IO.File.OpenRead(filename))
        return BitConverter.ToString(shA256.ComputeHash((Stream) inputStream)).Replace("-", "");
    }
  }

  public static bool VerifySha(string filePath, string sha)
  {
    bool flag = CApMaintenanceUpdatesApp.ComputeSha256Hash(filePath).ToUpper() == sha.ToUpper();
    if (!flag)
      CApMaintenanceUpdatesApp.WriteErrorLogMessage($"Invalid Hash [{sha}] for file [{filePath}].");
    return flag;
  }

  public string GetSetupTargetDownloadLocation(string setupLocation)
  {
    char ch = setupLocation.StartsWith("http") ? '/' : '\\';
    string pattern = "(Tecnomatix_.*)&";
    System.Text.RegularExpressions.Match match = Regex.Match(setupLocation, pattern);
    if (match.Groups.Count == 2)
    {
      string path2 = match.Groups[1].ToString();
      return Path.Combine(CApMaintenanceUpdatesApp.GetDownloadsPath(), path2);
    }
    CApMaintenanceUpdatesApp.WriteErrorLogMessage("Cannot get filename from Url:" + setupLocation);
    return (string) null;
  }

  public bool IsMaintenanceUpdateDownloaded(VersionDeclarationEntry info)
  {
    bool flag = false;
    string downloadLocation = this.GetSetupTargetDownloadLocation(info.Setup);
    if (System.IO.File.Exists(downloadLocation))
      flag = CApMaintenanceUpdatesApp.VerifySha(downloadLocation, info.Hash);
    return flag;
  }

  private static string GetRegStringValue(string keyPath, string valueName)
  {
    RegistryKey registryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32).OpenSubKey(keyPath);
    if (registryKey != null)
    {
      object obj = registryKey.GetValue(valueName);
      if (obj != null)
        return obj.ToString();
    }
    return (string) null;
  }

  public static bool DoesMaintenanceUpdateFailed()
  {
    bool flag = false;
    string name = TxGeneralAppUtil.GetRegistryPath() + "\\eMPower\\InstalledProducts\\Patches";
    using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(name, false))
    {
      if (registryKey != null)
        flag = registryKey.GetValue("Tecnomatix_MP_Installing") != null;
    }
    return flag;
  }

  public static bool IsMaintenanceUpdateRunning()
  {
    return ((IEnumerable<Process>) Process.GetProcesses()).FirstOrDefault<Process>((Func<Process, bool>) (x => x.ProcessName.StartsWith("Tecnomatix_MP_") || x.ProcessName.StartsWith("Tecnomatix_Update_"))) != null;
  }

  private string GetCurrentVersion()
  {
    string currentVersion = (string) null;
    string name = TxGeneralAppUtil.GetRegistryPath() + "\\eMPower";
    using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(name, false))
    {
      if (registryKey != null)
      {
        object obj1 = registryKey.GetValue("CommonFilesFolderVersion");
        object obj2 = registryKey.GetValue("TecnomatixProductVersion");
        currentVersion = obj2 != null ? obj2.ToString() : obj1.ToString();
      }
    }
    return currentVersion;
  }

  private bool IsNewVersionInternal(string currentVersion, string versionString)
  {
    if (currentVersion == null || versionString == null)
      return false;
    int num1 = int.Parse(currentVersion.Split('.')[0]);
    int num2 = int.Parse(versionString.Split('.')[0]);
    int num3 = int.Parse(currentVersion.Split('.')[1]);
    int num4 = int.Parse(versionString.Split('.')[1]);
    bool flag1 = num2 > num1;
    bool flag2 = num2 == num1;
    bool flag3 = num4 > num3;
    return flag2 ? flag3 : flag1;
  }
}
